/*
* Java Card File Parser 
* Based on openjcvm project 
*/

package org.naive.metawatch.converter.exp;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.List;
import org.naive.metawatch.converter.parser.*;

/**
 *
 * @author Andrew Butenko
 */
public class ConstantPool extends Parseable implements NameResolver {

    private static final byte CONSTANT_Package = (byte) 13;
    private static final byte CONSTANT_Classref = (byte) 7;
    private static final byte CONSTANT_Integer = (byte) 3;
    private static final byte CONSTANT_Utf8 = (byte) 1;

    private final List<Parseable> constants = new ArrayList<>();
    
    @Override
    public void parse(ParseContext px) throws ParseException {
        final short num = px.readShort();
        for(int i =0;i<num;i++) {
            Parseable constant = null;
            switch (px.readByte()) {
                case CONSTANT_Utf8:
                    constant = new StringConstant();
                    break;
                case CONSTANT_Package:
                    constant = new PackageConstant();
                    break;
                case CONSTANT_Integer:
                    constant = new IntConstant();
                    break;
                case CONSTANT_Classref:
                    constant = new ClassRefConstant();
                    break;
            }
            constant.parse(px);
            constants.add(constant);
        }
    }

    public static class PackageConstant extends Parseable{
        @ParsedInt(FieldSize.BYTE)
        public byte flag;
        @ParsedInt(FieldSize.SHORT)
        public int nameIndex;
        @ParsedInt(FieldSize.BYTE)
        public int minorVersion;
        @ParsedInt(FieldSize.BYTE)
        public int majorVersion;
        @ParsedIntArray(indexSize= FieldSize.BYTE, itemSize= FieldSize.BYTE)
        public byte[] aid;
    }

    public static class IntConstant extends Parseable {

        @ParsedInt(FieldSize.INT)
        public int value;
    }

    public static class ClassRefConstant extends Parseable {

        @ParsedInt(FieldSize.SHORT)
        public int index;

        @Override
        public String toString(String indent, NameResolver r) {
            return r.getName(index);
        }
    }

    public static class StringConstant extends Parseable {

        public String value;

        @Override
        public void parse(ParseContext px) throws ParseException {
            final short len = px.readShort();
            value = px.readUtf8(len);
        }

        @Override
        public String toString(String indent, NameResolver r) {
            return value;
        }
    }
    
    public Object get(int index) {
        return constants.get(index);
    }
    
    public String getString(int index) {
        return constants.get(index).toString("", this);
    }
    
    @Override
    public String getName(int index) {
        return getString(index);
    }
}
